<template>
  <!-- {{ fileList }} -->
  <n-upload :directory-dnd="directoryDnd" :custom-request="customRequest" ref="upload" :multiple="multiple"
    class="f-ad-upload" :default-upload="defaultUpload" :action="params.action" :headers="headers" :max="max"
    @on-update:file-list="fileListChange" :data="params.data" :disabled="disabled" :accept="accept"
    :show-file-list="false" :with-credentials="true" @before-upload="beforeUpload" @finish="onFinish" @remove="onRemove"
    @error="onError" @change="onChange">
    <n-upload-dragger style="padding: 0;">
      <slot>
        <div class="media-component-container ">
          <div class="creative-upfile-info" v-if="(!fileInfo.media_url && !load)">
            <div class="creative-upfile-specs" v-if="!rules.suggest.length">
              (要求尺寸: {{ rules.rect[0] }}px × {{ rules.rect[1] }}px )
            </div>
            <div class="creative-upfile-specs" v-if="rules.suggest.length">
              (推荐尺寸: {{ rules.suggest[0] }}px × {{ rules.suggest[1] }}px )
            </div>
            <div class="creative-upfile-text">点击或拖拽上传</div>
            <div class="creative-upfile-specs" v-if="rules.ratio.length">{{ rules.ratio[0] }}: {{
              rules.ratio[1] }}</div>
            <div class="creative-upfile-tip">
              <span>{{ rulesTips }}</span>
            </div>
          </div>
          <!-- <n-spin v-if="!load" class="load-spin"></n-spin> -->
          <div class="creative-upfile-display" v-if="fileInfo.media_url || load">
            <n-spin v-if="load" style="width: 100%;height: 100%;position: absolute;"></n-spin>
            <img style="max-width: 100%;max-height: 100%;" v-if="fileInfo.meta_type == 'image' && fileInfo.media_url"
              :src="fileInfo.media_url" fit="cover" />
            <video v-if="fileInfo.meta_type == 'video' && fileInfo.media_url" :src="fileInfo.media_url"
              controlsList="nodownload" @click.stop style="max-height: 100%;max-width: 100%;" ref="videoRef" />
            <div class="creative-upfile-operation" v-if="fileInfo.media_url">

              <n-icon class="play-btn" size="40" color="white" @click.stop="triggerVideo"
                v-if="fileInfo.meta_type == 'video'">
                <PlayCircleOutlined v-if="isPaused"></PlayCircleOutlined>
                <PauseCircleOutlined v-else></PauseCircleOutlined>
              </n-icon>
              <!-- <n-popover v-if="fileInfo.meta_type == 'video'" >
                <template #trigger>
                  <div size="small" class="view-keyframeImageurl">查看缩略图</div>
                </template>
<img width="300" :src="fileInfo.keyFrameImageUrl" alt="">
</n-popover> -->
              <n-icon class="icon" size="20" color="red" @click.stop="removeMeida">
                <CloseCircleFilled></CloseCircleFilled>
              </n-icon>
            </div>
          </div>
        </div>

      </slot>
    </n-upload-dragger>
  </n-upload>



</template>
<script setup lang="ts">
import { computed, ref, toRef, watch } from 'vue';
import { NUpload, useMessage, NIcon, NSpin, NImage, NPopover, NUploadDragger, NButton } from 'naive-ui';

const message = useMessage()
import { bytesToSize } from '@/utils/index'
import { is99Mall, isHQSC, isHZL, isSaaS } from '@/utils/is';
import { TOKEN_LOGIN_KEY, TOKEN_STORE_KEY } from '@/enums/cacheEnum'
import { local_storage } from '@/utils/storage'
const emit = defineEmits(['before-upload', 'finish', 'error', 'remove', 'progress']);
import { CloseCircleFilled, PlayCircleOutlined, PauseCircleOutlined } from '@vicons/antd'
import { v4 as uuidv4 } from 'uuid'

const props = defineProps({
  disabled: {
    type: Boolean,
    default: false
  },

  customRequest: {

  },
  defaultUpload: {
    default: true
  },

  max: {
    default: undefined
  },
  directoryDnd: {
    default: true,
  },

  // 只在单个文件上传有效
  multiple: {
    default: false,
  },
  value: {
    default: {
      meta_type: '',
      media_url: '',
    },
  },
  params: {
    type: Object,
    default: () => ({
      accept: 'image/*',
      action: '',
      data: {}
    })
  },
  rules: {
    type: Object,
    default: () => ({
      rect: [],

      suggest: [],
      // kb
      size: 512000,
      ratio: [12, 9],
      duration: [],
      file_format: [],
    })
  }
})


const controlValue = toRef(props, 'value');
// 只在单个文件上传有效
const fileInfo = ref<any>(props.value);
watch(controlValue, () => {
  fileInfo.value = props.value;
})

const load = ref(false);


// const fileList = ref([]);
const videoRef = ref();
const isPaused = ref(true);

function triggerVideo() {
  const video = videoRef.value;
  if (video) {
    isPaused.value = !video.paused;
    video.paused ? video.play() : video.pause();
  }

}

const accept = computed<string>(() => {
  const file_format = props.rules.file_format && props.rules.file_format.length ? props.rules.file_format : [];
  if (!file_format.length) return props.params.accept;
  return file_format.map((_: any) => {
    const [__, ___, meta] = _.split('_');
    return '.' + meta.toLocaleLowerCase();
  }).join(',')
})

const AcceptIsImage = computed(() => {
  return /PNG|png|JPG|jpg|JPEG|jpeg/.test(accept.value);
})

const rulesTips = computed(() => {
  const { duration, file_format, size } = props.rules;
  const filetext = (file_format || []).map(_ => {
    return _.replace(/MEDIA_TYPE_|IMAGE_TYPE_/, '');
  }).join('/');
  const [durMin, durMax] = duration || [];
  const durtext = duration && duration.length ? `，时长≥${durMin}s，≤${durMax}s，必须带有声音` : '';
  const sizetext = +size ? `，<${ size < 1024 ? size + 'K' : ((size || 0) / 1024).toFixed(2) + 'M'}` : '';
  return `${filetext}${sizetext}${durtext}`;
})











const headers = computed(() => {
  const System = is99Mall ? 1 : isHZL ? 2 : isHQSC ? 3 : isSaaS ? 4 : null
  return {
    // 'Content-Type': 'application/x-www-form-urlencoded',
    accessToken: local_storage.get(TOKEN_STORE_KEY) || local_storage.get(TOKEN_LOGIN_KEY),
    'x-system': System,

    // key: 'test/images/dc_1720285309728_500-1.jpg',
    // token: 'bBAv6Q6-HLMdjm_dHQlwmJihXx20d-Y-BbaXO8Ti:7ip2wmSqvbI1tU6jFQYbWD7nPCM=:eyJzY29wZSI6InRtZGMiLCJkZWFkbGluZSI6MTcyMDI4ODkwOX0='
  }
})









function sizeValidate(file: any) {

  const rulesSize = (props.rules.size || 100);
  // console.log(file.size, 'props.rules.size', rulesSize * 1024)
  if (rulesSize && (file.size) > (rulesSize * 1024)) {
    return false;
  }
  return true;

}

function proportionValidate(file: { width: number, height: any } & any) {
  const rulesRect = props.rules.rect || [];
  if (!rulesRect.length) return true;
  const [width, height] = rulesRect;
  const _width = Math.abs(width - file.width)
  const _height = Math.abs(height - file.height);
  if (width && (_width > 5 || _height > 5)) {
    return false
  }


  return true;
}


function videoDurationValidate(file: { duration: number } & any) {
  const rulesDuration = props.rules.duration || [];
  if (!rulesDuration.length) return true;
  if (!(file.duration <= rulesDuration[1] && file.duration >= rulesDuration[0])) {
    return false;
  }
  return true;
}



function getFileType(file: any) {

  const fileBody = file.file;
  if (fileBody.type.indexOf('image') !== -1) {
    return 'image'

  } else if (fileBody.type.indexOf('video') !== -1) {
    return 'video'
  }
  return 'other'
}


function getImageInfo(file: any): any {
  return new Promise((resolve, reject) => {
    const URL = window.URL || window.webkitURL;
    const originFile = file.file;
    const src = URL.createObjectURL(originFile)
    const image = new Image()
    image.src = src
    image.onload = () => {
      resolve({
        width: image.width,
        height: image.height
      })
    }
    image.onerror = () => {
      reject({
        width: 0,
        height: 0
      })
    }

  })


}

function getVideoInfo(file: any): any {
  return new Promise((resolve, reject) => {
    const URL = window.URL || window.webkitURL;
    const originFile = file.file;

    const src = URL.createObjectURL(originFile)
    const video = document.createElement('video');

    video.src = src
    video.oncanplay = () => {
      resolve({
        width: video.videoWidth,
        duration: video.duration,
        height: video.videoHeight
      })
    }
    video.onerror = () => {
      reject({
        width: 0,
        duration: 0,
        height: 0
      })
    }

  })

}



function createSingleFile(data: any) {
  fileInfo.value = Object.assign(fileInfo.value, data);
}

async function beforeUpload({ file, fileList }: any) {
  const rect = props.rules.rect || [];
  const duration = props.rules.duration || [];
  const originFile = file.file;
  const metaType = getFileType(file);
  if (!sizeValidate(originFile)) {
    message.warning(`请上传≤${bytesToSize(props.rules.size)}的素材`)
    return false;
  }
  const info = metaType === 'image' ? await getImageInfo(file) : await getVideoInfo(file);
  if (!proportionValidate(info)) {
    // console.log(rect, 'rect');
    message.warning(`请上传推荐尺寸 ${rect[0]}px X ${rect[1]}px 的素材`);
    return false;
  }

  if (metaType === 'video' && !videoDurationValidate(info)) {
    message.warning(`当前视频时长为：${info.duration}s，不符合要求, 应该为≥${duration[0]}s，≤${duration[1]}s, 请重新上传`);
    return false;
  }
  const refile = {
    id: file.id,
    batchId: file.batchId,
    imageWidth: info.width,
    imageHeight: info.height,
    meta_type: metaType,
    // mediaType: 1,
    fileSize: originFile.size,
    uuid: uuidv4()
  }
  createSingleFile(refile);
  load.value = true;
  emit('before-upload', Object.assign({}, refile));
  return true;

}


function onChange(options: any) {
  if (!props.defaultUpload) {
    var reader = new FileReader();
    reader.onload = function (event: any) {
      var base64 = event.target.result;
      fileInfo.value.media_url = base64;
      fileInfo.value.meta_type = 'image';
      load.value = false;
    };
    reader.readAsDataURL(options.file.file);
  }

}

function fileListChange(data: any) {
  console.log('fileListChange: ')
}

function onFinish({ file, event }: any) {

  const { success, data, msg } = JSON.parse((event?.target as XMLHttpRequest).response);
  const messageText = msg || '上传出错，请校对是否符合上传要求'
  // 此处可能需要根据 response 的值，校验接口是否成功
  load.value = false;
  fileInfo.value.loading = false;
  if (success && data && (data.media_id || data.mediaId || data.imageId || data.fileUrl || data.previewUrl)) {
    const metaType = getFileType(file);

    const refile = {
      ...file,
      ...data,
      media_url: data.previewUrl,
      meta_type: metaType,
      mediaId: '' + data.mediaId,
      media_id: '' + data.mediaId,
    };
    createSingleFile(refile);
    if (metaType == 'video') {
      isPaused.value = true;
    }

    emit('finish', Object.assign({}, file, refile, {
      id: file.id
    }));


  } else {
    message.error(messageText)
    emit('error', ...arguments)
  }

}

function onRemove() {
  // fileInfo.value = {};
  // emit('remove', ...arguments)
  removeMeida({});

}

function onError() {
  message.error('抱歉，上传失败；请检查文件是否超出限制~', { duration: 5 * 1000 })
  emit('error', ...arguments);
  load.value = false;

}

function onProgress() {
  emit('progress', ...arguments)

}


function removeMeida(e: any) {
  fileInfo.value = {};
  load.value = false;
  emit('remove', fileInfo)
}



const upload = ref();
async function submit() {
  try {
    const info = await upload.value.submit();
    return Promise.resolve(info);
  } catch (error) {
    return Promise.reject()
  }
}

defineExpose({
  submit: submit
})

</script>
<style lang="scss">
.f-ad-upload {
  height: 100%;
  width: 100%;
  cursor: pointer;

  .n-upload-trigger {
    height: 100%;
    width: 100%;
  }
}



.creative-upfile-group {
  height: 160px;
  display: flex;
  align-items: center;
  border: 1px solid #e6e8ed;
  border-radius: 4px;
  width: 100%;
}

.creative-upfile-group-item {
  height: 100%;
  background-color: #f5f6f8;
  flex: 1;
  position: relative;
}

.creative-upfile-group-item+.creative-upfile-group-item {
  border-left: 1px solid #e6e8ed;
  margin-right: 0px;
}


.creative-upfile {
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0
}



.creative-upfile-info {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  color: rgba(0, 0, 0, .3);

  // &:hover .creative-upfile-tip {
  //   display: block;
  // }
}

.creative-upfile-info .creative-upfile-title {
  display: block;
  font-size: 22px;
  font-weight: 600
}

.creative-upfile-tip {
  // display: none;
  margin: 10px 20px 0;
  padding: 10px 0 0;
  border-top: 1px solid #dfe1e6;
  text-align: center;
  font-size: 12px;
}


.creative-upfile-display,
.creative-upfile-operation {

  position: absolute;
  height: 90%;
  max-width: 252px;
  width: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.creative-upfile-display {
  background-color: #eceef1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
}

.creative-upfile-display .spin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.creative-upfile-operation {
  display: none;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, .3);

  .play-btn {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .icon {
    position: absolute;
    right: 0;
    top: 0;
  }

  .view-keyframeImageurl {
    position: absolute;
    bottom: 12px;
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 12px;
    border-radius: 3px;
    background-color: rgba(0, 0, 0, 0.3);
    font-size: 13px;
    color: #fff;
  }
}


.creative-upfile-display:hover .creative-upfile-operation {
  display: block;
  z-index: 1;

}

.media-component-container {

  height: 160px;
  background-color: #f5f6f8;
  flex: 1;
  position: relative;
  border: 1px solid #e6e8ed;
  border-radius: 4px;
  width: 100%;
}

.creative-group-item+.creative-group-item {
  border-left: 1px solid #e6e8ed;
  margin-right: 0px;
}

.creative-upfile-text {
  font-weight: 600;
  color: var(--gray-7)
}
</style>
